package com.chap6;

import java.util.Random;
import java.util.concurrent.Phaser;

/**
 * <p>
 * <code>PhaserDemo</code>
 * </p>
 *
 * @author junbao3
 * TODO
 * @date 2023-03-20 6:22
 * Copyright (C) 2021 IFlyTek. All rights reserved.
 */
public class PhaserDemo {
    public static void main(String[] args) {
        final Phaser phaser = new Phaser(){
            //阶段到达动作
            @Override
            protected boolean onAdvance(int phase, int registeredParties) {
                //参与者数量，去除主线程
                int staff = registeredParties-1;
                //3个阶段
                switch (phase){
                    case 0:
                        System.out.println("大家都到公司了，出发去公园，人数："+staff);
                        break;
                    case 1:
                        System.out.println("大家都到公园门口了，出发去餐厅，人数："+staff);
                        break;
                    case 2:
                        System.out.println("大家都到餐厅了了，开始用餐，人数："+staff);
                        break;

                }
                //只剩下主线，返回true，代表终止
                return registeredParties == 1;
            }
        };

        //注册主线程，让主线程全程参与，主线程得知道每个阶段发生了什么事情
        phaser.register();
        final StaffTask staffTask = new StaffTask();
        //3个全程参与团建的员工
        for (int i = 0; i < 3; i++) {
            phaser.register();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        staffTask.step1Task();
                        //到达后等其他任务到达
                        //都到达之后，表示整个过程到了第一阶段，执行onAdvance phase=0
                        phaser.arriveAndAwaitAdvance();

                        staffTask.step2Task();
                        phaser.arriveAndAwaitAdvance();

                        staffTask.step3Task();
                        phaser.arriveAndAwaitAdvance();

                        staffTask.step4Task();
                        //完成了 注销离开
                        phaser.arriveAndDeregister();

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();

        }

        //2个不聚餐的员工加入
        for (int i = 0; i < 2; i++) {
            phaser.register();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        staffTask.step1Task();
                        //到达后等其他任务到达
                        phaser.arriveAndAwaitAdvance();

                        staffTask.step2Task();
                        System.out.println("员工【"+Thread.currentThread().getName()+"】回家了");
                        //完成了 注销离开
                        phaser.arriveAndDeregister();

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();

        }

        while(!phaser.isTerminated()){
            int phase = phaser.arriveAndAwaitAdvance();
            if (phase==2){//第三个阶段
                //去餐厅的阶段 又增加了4个人 参加晚上的聚餐
                for (int i = 0; i < 4; i++) {
                    phaser.register();
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                staffTask.step3Task();
                                phaser.arriveAndAwaitAdvance();
                                staffTask.step4Task();
                                phaser.arriveAndDeregister();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }).start();
                }
            }
        }
    }

    static final Random random = new Random();

    static class StaffTask{
        public void step1Task() throws InterruptedException {
            //第一阶段：来公司集合
            String staff = "员工【"+Thread.currentThread().getName()+"】";
            System.out.println(staff+"从家出发了...");
            Thread.sleep(random.nextInt(5000));
            System.out.println(staff+"到达公司");
        }
        public void step2Task() throws InterruptedException {
            //第二阶段：出发去公园
            String staff = "员工【"+Thread.currentThread().getName()+"】";
            System.out.println(staff+"出发去公园玩");
            Thread.sleep(random.nextInt(5000));
            System.out.println(staff+"到达公园门口集合");
        }
        public void step3Task() throws InterruptedException {
            //第三阶段：去餐厅
            String staff = "员工【"+Thread.currentThread().getName()+"】";
            System.out.println(staff+"出发去餐厅");
            Thread.sleep(random.nextInt(5000));
            System.out.println(staff+"到达餐厅");
        }
        public void step4Task() throws InterruptedException {
            //第三阶段：就餐
            String staff = "员工【"+Thread.currentThread().getName()+"】";
            System.out.println(staff+"开始用餐");
            Thread.sleep(random.nextInt(5000));
            System.out.println(staff+"用餐结束，回家");
        }
    }

}
